package com.wonders.frame.service;

import com.gcr.util.StringUtil;
import com.wonders.frame.common.Enum.CommonCodeEnum;
import com.wonders.frame.common.Enum.CommonSourceKeyEnum;
import com.wonders.frame.common.Enum.InitCommonSourceEnum;
import com.wonders.frame.common.Enum.RemovedCodeEnum;
import com.wonders.frame.common.Sorts;
import com.wonders.frame.entity.AuthAccount;
import com.wonders.frame.entity.AuthOrga;
import com.wonders.frame.entity.AuthPermission;
import com.wonders.frame.entity.Tree.SelectTreeNodeData;
import com.wonders.frame.entity.form.AuthOrgaForm;
import com.wonders.frame.repository.AuthAccountRepository;
import com.wonders.frame.repository.AuthOrgaRepository;
import com.wonders.frame.repository.core.CoreRepository;
import com.wonders.frame.service.Core.CoreCurdService;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

@Service
public class AuthOrgaService extends CoreCurdService<AuthOrga> {
    Logger log = LoggerFactory.getLogger(AuthOrgaService.class);
    @Autowired
    private AuthOrgaRepository repo;

    @Autowired
    private AuthAccountRepository accountRepo;


    protected CoreRepository getRepository(){
        return repo;
    }


    //验证机构代码唯一性
    public AuthOrga checkUnique(String orgaCode){
        List<AuthOrga> list = repo.checkUnique(orgaCode);
        if(list!=null&&list.size()!=0){
            return list.get(0);
        }else{
            return null;
        }
    }

    //验证机构下是否存在用户
    public Boolean isExistAccount(String orgaId){
        List<AuthAccount> authAccountList = accountRepo.getAccountByOrga(orgaId);
        if(authAccountList != null && authAccountList.size()>0){
            return true;
        }else{
            return false;
        }
    }

    //根据OrgaId获取该部门/机构下所有用户
    public List<AuthAccount> getAllUser(String orgaId){
        /**
         *  1.由部门/机构的OrgaId得到其所有下属的部门机构OrgaId
         *  2.将上述所有OrgaId分别作为参数传给查询方法执行，得到相应的List<AuthAccount>
         *  3.合并所有List<>为一个List<>,将其传回前台显示
         */
        //由根结点OrgaId得到所有下属Orga
        List<AuthOrga> authOrgas=repo.findByParentId(orgaId);
        //传参执行得到若干List<>并合并（部门唯一不去重）
        List<AuthAccount> authAccountAllList =accountRepo.getAccountByOrga(orgaId);
        for(int i=0;i<authOrgas.size();i++){
            authAccountAllList.addAll(accountRepo.getAccountByOrga(authOrgas.get(i).getId()));
        }
        //返回合并后的list<>
        return authAccountAllList;
    }


    public Page<AuthOrga> getList(AuthOrgaForm user) {
        Specification<AuthOrga> specification = new Specification<AuthOrga>() {

            /**
             * 构造断言
             * @param root 实体对象引用
             * @param query 规则查询对象
             * @param cb 规则构建对象
             * @return 断言
             */
            @Override
            public Predicate toPredicate(Root<AuthOrga> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>(); //所有的断言
                if(!StringUtil.isEmpty(user.getOrgaName())){ //添加断言
                    Predicate likeNickName = cb.like(root.get("orgaName").as(String.class),user.getOrgaName()+"%");
                    predicates.add(likeNickName);
                }
                return cb.and(predicates.toArray(new Predicate[0]));
            }
        };
        //分页信息
        Sort sort = new Sort(Sort.Direction.DESC, "orgaName");
        Pageable pageable = PageRequest.of(user.getPageNum() -1 , user.getPageSize(), sort);
        //查询
        return repo.findAll(specification, pageable);
    }


    public List<AuthOrga> findAll(){

        return repo.getAllAuthOrga();
    }

    public AuthOrga save(AuthOrgaForm authOrgaForm) {
        AuthOrga authOrga = new AuthOrga();
        BeanUtils.copyProperties(authOrgaForm,authOrga);
        if(StringUtil.isEmpty(authOrga.getId())){
            //新增，验证机构代码唯一性
            log.debug("new authOrga");
            authOrga.setRemoved(0);
            authOrga.setCrtDate(new Date());
            authOrga = repo.save(authOrga);
            //保存序列 父级序列 + 本id + .
            if(!StringUtil.isEmpty(authOrga.getParentId())){
                String parentIndex = repo.findById(authOrga.getParentId()).get().getOrgaSerachindex();
                authOrga.setOrgaSerachindex(parentIndex+"."+authOrga.getId());
            }else{
                authOrga.setOrgaSerachindex(authOrga.getId()+".");
            }
        }else{
            log.debug("modify authOrga");
            //查所有子节点 不设置的话 会把子节点的parentId赋空
            List<AuthOrga> list = repo.findByParentIdAndRemoved(authOrga.getId(), RemovedCodeEnum.AVAILABLE.getCode());
            authOrga.setOrgaChildren(list);
            authOrga.setUpdDate(new Date());
        }
        return repo.save(authOrga);
    }

    public List<SelectTreeNodeData> getAccountOrgaNodeTree(List<AuthOrga> orgas){
        List<SelectTreeNodeData> nodes = new ArrayList<SelectTreeNodeData>();
        for(AuthOrga orga : orgas){
            if(orga.getParentId() == null){
                nodes.add(getOrgaNode(orga));
            }else{
                String pId = orga.getParentId();//不存在于orgas之中
                Boolean b = true;
                for(AuthOrga o : orgas){
                    if(pId.equals(o.getId())){
                        b = false;
                        break;
                    }
                }
                if(b){
                    nodes.add(getOrgaNode(orga));
                }
            }
        }
        return nodes;
    }

    public List<SelectTreeNodeData> getOrgaNodeTree(){
        List<SelectTreeNodeData> nodes = new ArrayList<SelectTreeNodeData>();
        List<AuthOrga> orgas = repo.getAllAuthOrga();
        for(AuthOrga orga : orgas){
            // 若存在parentNode，则该节点在child中显示，不需要加到根节点中
            if(orga.getParentId() == null){
                nodes.add(getOrgaNode(orga));
            }
        }
        return nodes;
    }

    /**
     * 递归调用，初始化机构树对象
     * @param orga
     * @return
     */
    private SelectTreeNodeData getOrgaNode(AuthOrga orga){
        SelectTreeNodeData nodeData = new SelectTreeNodeData();
        nodeData.setKey(orga.getId());
        nodeData.setValue(orga.getId());
        nodeData.setTitle(orga.getOrgaName());
        nodeData.setOrga_type(orga.getOrgaType());
        if(orga.getOrgaChildren() != null){
            List<SelectTreeNodeData> nodes = new ArrayList<SelectTreeNodeData>();
            for(AuthOrga o : orga.getOrgaChildren()){
                if(o.getRemoved()==0){
                    nodes.add(getOrgaNode(o));
                }
            }
            nodeData.setChildren(nodes);
        }
        return nodeData;
    }

    /**
     * 根据id查看单节点信息
     */
    public AuthOrga getNodeById(String id){
        if(Strings.isNotEmpty(id)){
            AuthOrga authOrga = repo.findById(id).get();
            return authOrga;
        }
        return null;
    }

    //删除节点
    public CommonCodeEnum deleteOrgaById (String id) {
        try {
            //逻辑删除
            AuthOrga authOrga = repo.findById(id).get();
            authOrga.setRemoved(1);
            repo.save(authOrga);
        }catch (Exception e){
            e.printStackTrace();
            return CommonCodeEnum.ERROR;
        }
        return CommonCodeEnum.SUCCESS;
    }
    //根据OrgaProperty 获取当前节点及以下节点
    public List<SelectTreeNodeData> getOrgaTreeByOrgaProperty(String orgaProperty){
        Map<String, Object> map= InitCommonSourceEnum.getCommonSource(CommonSourceKeyEnum.ORGA.name());
        List<SelectTreeNodeData> list = new ArrayList<SelectTreeNodeData>();
        if(!StringUtils.isEmpty(orgaProperty)){
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                AuthOrga authOrga=((AuthOrga) entry.getValue());
                if(orgaProperty.equals(authOrga.getOrgaProperty())&&authOrga.getRemoved()==RemovedCodeEnum.AVAILABLE.getCode()){
                    list.add(getOrgaNode(authOrga));
                }
            }
        }
        return list;
    }

    //根据orgaCode 获取当前节点及以下节点
    public List<SelectTreeNodeData> getOrgaTreeByOrgaCode(String orgaCode){
        Map<String, Object> map=InitCommonSourceEnum.getCommonSource(CommonSourceKeyEnum.ORGA.name());
        List<SelectTreeNodeData> list = new ArrayList<SelectTreeNodeData>();
        if(!StringUtils.isEmpty(orgaCode)){
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                AuthOrga authOrga=((AuthOrga) entry.getValue());
                if(orgaCode.equals(authOrga.getOrgaCode())&&authOrga.getRemoved()==RemovedCodeEnum.AVAILABLE.getCode()){
                    list.add(getOrgaNode(authOrga));
                }

            }
        }
        return list;
    }

    //根据orgaId 获取当前节点及以下节点
    public List<SelectTreeNodeData> getOrgaTreeByOrgaId(Map<String, Object> map,String orgaId){
        List<SelectTreeNodeData> list = new ArrayList<SelectTreeNodeData>();
        if(!StringUtils.isEmpty(orgaId)){
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                AuthOrga authOrga=((AuthOrga) entry.getValue());
                if(orgaId.equals(authOrga.getId())&&authOrga.getRemoved()==RemovedCodeEnum.AVAILABLE.getCode()){
                    list.add(getOrgaNode(authOrga));
                }
            }
        }
        return list;
    }

    private List<String> getSelectTreeNodeDataOrgaId(List<String> list,SelectTreeNodeData selectTreeNodeData){
        list.add(selectTreeNodeData.getValue());
        List<SelectTreeNodeData> children=selectTreeNodeData.getChildren();
        if(!CollectionUtils.isEmpty(children)){
            for (SelectTreeNodeData data:children){
                getSelectTreeNodeDataOrgaId(list,data);
            }
        }
        return list;
    }

    //根据orgaId 获取当前节点及子节点数据  然后返回选中节点(当前节点)
    public Map<String,Object> getOrgaTreeNodeAndChecked(String orgaId){
        Map<String, Object> map=InitCommonSourceEnum.getCommonSource(CommonSourceKeyEnum.ORGA.name());
        //获得当前节点及当前节点的字节点
        List<SelectTreeNodeData> list=getOrgaTreeByOrgaId(map,orgaId);
        Map<String,Object> result=new HashMap<>();
        result.put("checkedData",orgaId);
        result.put("treeData",list);
        return result;
    }

    public String getChildOrgas(String orgaId){
        String ogras = "";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("parentId_eq", orgaId);
        List<AuthOrga> os = findAllByParams(map);
        for(AuthOrga o : os){
            ogras += o.getId() + ",";
        }
        return ogras;
    }
    /**
     * @Author 顾乘瑞
     * @Description 获取区划为当前登录用户所属区划的orgaId（like前两位）
     *              eg: 当前为310000，返回310001、312002等
     * @Date 2019/4/2
     * @Param
     * @return
     */
    public String getLikeOrga1(String orgaId){
        AuthOrga orga = findById(orgaId);
        return getLikeOrga(orga.getOrgaArea(), 2);
    }
    /**
     * @Author 顾乘瑞
     * @Description 获取区划为当前登录用户所属区划的orgaId（like前四位）
     *              eg: 当前为310000，返回310001、310004等
     * @Date 2019/4/2
     * @Param
     * @return
     */
    public String getLikeOrga2(String orgaId){
        AuthOrga orga = findById(orgaId);
        return getLikeOrga(orga.getOrgaArea(), 6);
    }

    /**
     * @Author 顾乘瑞
     * @Description
     * @Date 2019/4/2
     * @Param orgaArea 所属区划代码
     * @Param length 按前几位like
     * @return
     */
    private String getLikeOrga(String orgaArea, Integer length){
        if(orgaArea == null){
            return null;
        }
        String ogras = "";
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("orgaArea_likeR", orgaArea.substring(0, length));
        List<AuthOrga> os = findAllByParams(map);
        for(AuthOrga o : os){
            ogras += o.getId() + ",";
        }
        return ogras;
    }

    //模糊查询机构节点
    public List<SelectTreeNodeData> findNodeByOrgaName(Boolean isAdmin,String orgaName,String deptId){
        List<AuthOrga> list = repo.findByOrgaNameLikeAndRemoved("%"+orgaName+"%",0);
        List<AuthOrga> list1 = repo.findLikeOrgaTree(deptId);
        //  List<AuthOrga> list=findAllByParamsAndSort(map,sortsList);
        List<SelectTreeNodeData> nodes = new ArrayList<SelectTreeNodeData>();
        for(AuthOrga authOrga:list){
            if(list1.contains(authOrga)||isAdmin) {
                SelectTreeNodeData nodeData = new SelectTreeNodeData();
                nodeData.setKey(authOrga.getId());
                nodeData.setValue(authOrga.getId());
                nodeData.setTitle(authOrga.getOrgaName());
                nodeData.setOrga_type(authOrga.getOrgaType());
                nodeData.setChildren(new ArrayList<>());
                nodes.add(nodeData);
            }
        }
        return nodes;
    }

    //由机构id获得当前机构及子机构
    public List<AuthOrga> findAllOrgaByOrgaId(String orgaId){
        AuthOrga authOrga = repo.findByIdAndRemoved(orgaId,0);
        List<AuthOrga> authOrgas = new ArrayList<AuthOrga>();
        for(AuthOrga authOrga1 : authOrga.getOrgaChildren()){
            if(!authOrga1.getId().isEmpty())
            authOrgas.addAll(findAllOrgaByOrgaId(authOrga1.getId()));
        }
        authOrgas.add(authOrga);
        return  authOrgas;
    }

}
